package com.xbongbong.paas.script.controller;

import com.alibaba.fastjson.JSON;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.pojo.repair.dto.RepairCustomerDTO;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.toolbox.wrap.XbbResponse;
import com.xbongbong.pro.constant.XbbProConstant;
import com.xbongbong.pro.domain.entity.UpdateDataEntity;
import com.xbongbong.pro.domain.entity.UpdateDataValueEntity;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.ext.CustomerEntityExt;
import com.xbongbong.saas.enums.business.CustomerCommunicateEnum;
import com.xbongbong.saas.enums.business.CustomerManagementEnum;
import com.xbongbong.saas.model.CustomerCommunicateModel;
import com.xbongbong.saas.model.CustomerModel;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.support.WriteRequest;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
import static org.elasticsearch.index.query.QueryBuilders.termsQuery;

/**
 * @author 吴峰
 * @date 2023/03/21 10:03
 */
@RestController
@RequestMapping(XbbProConstant.API_ROOT_PREFIX + "/script/communicate")
@Slf4j
public class RepairCustomerScriptController {

    @Resource
    private CustomerModel customerModel;
    @Resource
    private CustomerCommunicateModel customerCommunicateModel;

    @RequestMapping(value = "/repairCustomerId", method = RequestMethod.POST)
    public String fixCustomerId(@RequestBody @Valid  RepairCustomerDTO repairCustomerDTO, BindingResult bindingResult) throws XbbException {
        XbbResponse<String> response;
        if (bindingResult.hasErrors()) {
            String errMsg = Objects.requireNonNull(bindingResult.getFieldError()).getDefaultMessage();
            response = new XbbResponse<>(SystemErrorCodeEnum.API_ERROR_100002, errMsg);
        } else {
            try {
                String scriptVO = repairCustomer(repairCustomerDTO);
                response = new XbbResponse<>(scriptVO);
            } catch (XbbException e) {
                response = new XbbResponse<>(e);
            }
        }
        return JSON.toJSONString(response);
    }

    private String repairCustomerIdByName(RepairCustomerDTO repairCustomerDTO) throws XbbException {
        try {
            String corpid = repairCustomerDTO.getCorpid();
            Long formId = repairCustomerDTO.getFormId();
            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put(StringConstant.CORPID, corpid);
            param.put("formIdIn", repairCustomerDTO.getOldFormId());
            param.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
            Long id = 0L;
            param.put("pageSize", 5000);
            param.put("idGte", id);
            List<CustomerEntityExt> list = customerModel.findEntitysWithoutSub(param);
            // 更新失败的跟进记录
            List<Long> failList = new ArrayList<>();
            long now = DateTimeUtil.getInt();
            while (true) {
                if (list.size() == 0) {
                    break;
                }
                List<Long> customerIdList = new ArrayList<>();
                for (CustomerEntityExt customerEntityExt : list) {
                    customerIdList.add(customerEntityExt.getId());
                    String name = customerEntityExt.getData().getString(CustomerManagementEnum.NAME.getAttr());
                    //
                    BoolQueryBuilder boolQueryBuilder = boolQuery();
                    boolQueryBuilder.filter(termQuery(CustomerCommunicateEnum.getEsAttr4Keyword( CustomerCommunicateEnum.CUSTOMER_NAME_LINK_TEXT), name));
                    List<PaasFormDataEntityExt> customerCommunicateList = customerCommunicateModel.getCustomerCommunicateListByBoolQuery(corpid, boolQueryBuilder, PaasFormDataEntityExt.class, "data." + CustomerCommunicateEnum.COMMUNICATE_TIME.getAttr(), SortOrder.DESC);
                    List<UpdateDataEntity> updateList = new ArrayList<>();
                    customerCommunicateList.forEach(item -> {
                        UpdateDataValueEntity updateDataValueEntity = new UpdateDataValueEntity(CustomerCommunicateEnum.CUSTOMER_NAME.getAttr(), CustomerCommunicateEnum.CUSTOMER_NAME.getAttr(), customerEntityExt.getId().toString(), null, null);
                        List<UpdateDataValueEntity> updateDataValueEntities = new ArrayList<>();
                        updateDataValueEntities.add(updateDataValueEntity);
                        UpdateDataEntity updateDataEntity = new UpdateDataEntity(item.getDataId(), corpid, null, updateDataValueEntities, now);
                        updateList.add(updateDataEntity);
                    });
                    customerCommunicateModel.updateBatch(updateList, corpid, WriteRequest.RefreshPolicy.NONE);

                }
                id = list.get(list.size() - 1).getId();
                param.put("idGte", id);
                list = customerModel.findEntitysWithoutSub(param);

            }
            log.info("fail update = " + JSON.toJSONString(failList));
        } catch (Exception e) {
            log.error("RepairCustomerScriptController.repairCustomer", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
        return "success";
    }

    private String repairCustomer(RepairCustomerDTO repairCustomerDTO) throws XbbException {
        try {
            String corpid = repairCustomerDTO.getCorpid();
            Long formId = repairCustomerDTO.getFormId();
            List<CustomerEntityExt> list;
            // 更新失败的跟进记录
            List<Long> failList = new ArrayList<>();
            long now = DateTimeUtil.getInt();
            int pageNum = 0;
            int pageSize = 5000;
            Integer maxNum = repairCustomerDTO.getMaxNum();
            Long id = 0L;
            while (true) {
                Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                param.put(StringConstant.CORPID, corpid);
                param.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
                param.put("formIdIn", repairCustomerDTO.getOldFormId());
                param.put("idGte", id);
                param.put("pageSize", pageSize);
                param.put("orderByStr", " id ASC ");
                list = customerModel.findEntitysWithoutSub(param);
                if (CollectionsUtil.isEmpty(list)) {
                    break;
                }
                List<String> customerIdList = new ArrayList<>();
                Set<String> customerNameList = new HashSet<>();
                Map<String, String> oldNameMap = new HashMap<>(list.size());
                list.forEach(item->{
                    customerIdList.add(item.getId().toString());
                    String name = item.getData().getString(CustomerManagementEnum.NAME.getAttr());
                    if (StringUtil.isNotEmpty(name)) {
                        customerNameList.add(name);
                        oldNameMap.put(item.getId().toString(), name);
                    }
                });
                // 根据名称获取下新模板的客户
                List<PaasFormDataEntityExt> newCustomerList =  findCustomerByNameList(customerNameList, formId, corpid);
                Map<String, String> newNameMap = new HashMap<>(newCustomerList.size());
                newCustomerList.forEach(item->{
                    String name = item.getData().getString(CustomerManagementEnum.NAME.getAttr());
                    newNameMap.put(name, item.getId().toString());
                });
                BoolQueryBuilder boolQueryBuilder = boolQuery();
                boolQueryBuilder.filter(termsQuery(CustomerCommunicateEnum.getEsAttr4Keyword( CustomerCommunicateEnum.CUSTOMER_NAME), customerIdList));
                List<PaasFormDataEntityExt> customerCommunicateList = customerCommunicateModel.getCustomerCommunicateListByBoolQuery(corpid, boolQueryBuilder, PaasFormDataEntityExt.class, "data." + CustomerCommunicateEnum.COMMUNICATE_TIME.getAttr(), SortOrder.DESC);
                List<UpdateDataEntity> updateList = new ArrayList<>();
                customerCommunicateList.forEach(item->{
                    String customerId = item.getData().getString(CustomerCommunicateEnum.CUSTOMER_NAME.getAttr());
                    if (newNameMap.containsKey(oldNameMap.get(customerId))) {
                        UpdateDataValueEntity updateDataValueEntity = new UpdateDataValueEntity(CustomerCommunicateEnum.CUSTOMER_NAME.getAttr(), CustomerCommunicateEnum.CUSTOMER_NAME.getAttr(), newNameMap.get(oldNameMap.get(customerId)), null, null);
                        List<UpdateDataValueEntity> updateDataValueEntities = new ArrayList<>();
                        updateDataValueEntities.add(updateDataValueEntity);
                        UpdateDataEntity updateDataEntity = new UpdateDataEntity(item.getDataId(), corpid, null, updateDataValueEntities, now);
                        updateList.add(updateDataEntity);
                    } else {
                        failList.add(item.getDataId());
                    }
                });
                customerCommunicateModel.updateBatch(updateList, corpid, WriteRequest.RefreshPolicy.NONE);
                id = list.get(list.size()-1).getId();
                pageNum = list.size() + pageNum;
                log.info("总数量：" + maxNum+  "------已执行：" + pageNum + "---id：" + id );
            }
            log.info("fail update = " + JSON.toJSONString(failList));
        } catch (Exception e) {
            log.error("RepairCustomerScriptController.repairCustomer", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
        return "success";
    }


    private List<PaasFormDataEntityExt> findCustomerByNameList(Collection<String> nameList, Long formId, String corpid) throws XbbException {
        BoolQueryBuilder boolQueryBuilder = boolQuery();
        boolQueryBuilder.filter(termQuery("formId", formId));
        boolQueryBuilder.filter(termsQuery("del", Arrays.asList(DelEnum.NORMAL.getDel(), DelEnum.DELETE.getDel())));
        boolQueryBuilder.filter(termsQuery(CustomerManagementEnum.getEsAttr4Keyword( CustomerManagementEnum.NAME), nameList));
        List<PaasFormDataEntityExt> list = customerModel.getCustomerListByLinkIdIn(corpid, formId, boolQueryBuilder, PaasFormDataEntityExt.class, FieldTypeEnum.UPDATETIME.getAlias(), SortOrder.DESC, 0, 10000);
        return list;

    }


}
